package com.dotflat.rest.utils;/**
 * Created by admin on 2020/7/3.
 */

import com.alibaba.fastjson.JSONObject;
import com.starinside.wp.components.redis.RedisService;
import com.starinside.wp.components.redis.impl.RedisServiceImpl;
import com.starinside.wp.config.WxMpProperties;
import com.starinside.wp.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * 文件名：WXUtils
 * 作者： zenghl
 * 时间：2020/7/3 3:48 PM
 * 描述：
 */
@Slf4j
@Component
public class WXUtils {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RedisServiceImpl redisService;


    @Value("${wx.mp.web.appId}")
    private  String weChatMpAppId;
    @Value("${wx.mp.web.secret}")
    private  String appsecret;
    @Value("${wx.mp.web.token_url}")
    private  String cgiBinTokenUrl;
    @Value("${wx.mp.web.ticket_url}")
    private  String ticketUrl;
    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private static final Random RANDOM = new SecureRandom();


//    private static String cgiBinTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";


//    private static String ticketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";


    /**
     * jsapi_ticket
     */
    private static final String REIDS_JSAPI_TICKET_KEY = "jzyy-jsapiTicketToRedis";
    /**
     * token
     */
    private static final String REIDS_ACCESS_TOKEN_KEY = "jzyy-AccessTokenToRedis";


    // 微信公众号的AppID和小程序的AppID
//    private final String weChatMpAppId = "wxf97f55ca6b448528";
//    private final String appsecret = "ca483e4e24d4209dfde695209836b31b";
    /**
     * 签名算法
     签名生成规则如下：参与签名的字段包括noncestr（随机字符串）,
     有效的jsapi_ticket, timestamp（时间戳）,
     url（当前网页的URL，不包含#及其后面部分） 。
     对所有待签名参数按照字段名的ASCII 码从小到大排序（字典序）后，
     使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串string1。
     这里需要注意的是所有参数名均为小写字符。对string1作sha1加密，字段名和字段值都采用原始值，不进行URL 转义。
     */
    public Map<String,String> wxConfigParams(String webUrl){
        String jsapi_ticket = jsapiTicketFromRedis();
        String noncestr = generateNonceStr();
        String timestamp = getCurrentTimestamp()+"";
        String url = webUrl;

        String[] arr = new String[]{jsapi_ticket,noncestr, timestamp,url};
        String string1 = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;

//        log.info("拼接好的string1: "+string1);
        String sha1Hex = DigestUtils.sha1Hex(string1.getBytes());

        log.info("jsapi_ticket签名：  "+sha1Hex);

        Map<String,String> resMap = new HashMap<>();
        resMap.put("appId", weChatMpAppId);
        resMap.put("timestamp", timestamp);
        resMap.put("nonceStr", noncestr);
        resMap.put("signature", sha1Hex);

        return resMap;
    }

    /**
     * 将jsapiTicket存入redis中
     */
    public void jsapiTicketToRedis(){
        String url = ticketUrl;
        url = url.replace("ACCESS_TOKEN",accessTokenFromRedis());
        String res = HttpHelperUtil.get(url);
//        log.info("获取jsapiTicket： "+res);

        if(!StringUtils.isEmpty(res) && "ok".equals(WXKitUtils.errMsg(res))){
            JSONObject jsonObject = JSONObject.parseObject(res);
            String ticket = (String) jsonObject.get("ticket");
            Integer expires_in = (Integer) jsonObject.get("expires_in");
//            log.info("获取到ticket： "+ticket);
            redisUtil.set(REIDS_JSAPI_TICKET_KEY + weChatMpAppId, ticket, (int)((double)expires_in * 0.8));
        }else{
            log.info(WXKitUtils.errMsg(res));
        }
    }

    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }

    /**
     * 获取当前时间戳，单位秒
     * @return
     */
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis()/1000;
    }
    /**
     * 从reids中获取jsapiTicket
     * @return
     */
    public String jsapiTicketFromRedis(){
        String jsapiTicket = null;
        long expire = redisService.getExpire(REIDS_JSAPI_TICKET_KEY + weChatMpAppId);
        boolean b = redisService.hasKey(REIDS_JSAPI_TICKET_KEY + weChatMpAppId);

        if(expire == -2 || !b){
            jsapiTicketToRedis();
        }
        jsapiTicket = (String) redisService.get(REIDS_JSAPI_TICKET_KEY + weChatMpAppId);
//        log.info("从redis拿到了jsapiTicket: "+jsapiTicket);
        return jsapiTicket;
    }

    /**
     * 将accessToken存入redis中
     */
    public void accessTokenToRedis()  {

        String url = cgiBinTokenUrl.replace("APPID",weChatMpAppId)
                .replace("APPSECRET",appsecret);
        String res = HttpHelperUtil.get(url);

        if(!StringUtils.isEmpty(res) && "ok".equals(WXKitUtils.errMsg(res))){
            JSONObject jsonObject = JSONObject.parseObject(res);
            String access_token = (String) jsonObject.get("access_token");
            Integer expires_in = (Integer) jsonObject.get("expires_in");

            // 官方一般缓存2小时，但这里建议只缓存2小时以内：
            redisService.set(REIDS_ACCESS_TOKEN_KEY + weChatMpAppId, access_token,  (int)((double)expires_in * 0.8));

        }else{
            log.info(WXKitUtils.errMsg(res));
        }

    }

    /**
     * 从redis中获取accessToken
     * @return
     */
    public String accessTokenFromRedis()  {
        boolean b = redisService.hasKey(REIDS_ACCESS_TOKEN_KEY + weChatMpAppId);
        if(!b){
            accessTokenToRedis();
        }
        String token = (String) redisService.get(REIDS_ACCESS_TOKEN_KEY + weChatMpAppId);

        // 去除字符串中的多余双引号
//        String cleanedValue = token.replace("\"", "");
//        log.info("从redis中获取accessToken: {} ", token);
        return token;
    }

    /**
     * 从redis中，将accessToken删除
     */
    public void delAccessTokenFromRedis()  {
        redisService.del(REIDS_ACCESS_TOKEN_KEY + weChatMpAppId);
    }






}
